#region Copyright
/*
Copyright Notice: 
Use of this file, in source or binary form, is subject to the terms and conditions set forth 
in the included license.txt file.

this is Templates

*/
#endregion

#set($entity = $Neo.Entity)

using System;
using Castle.MonoRail.Framework;
using Castle.MonoRail.Framework.Helpers;
using Neo.Core;
using Neo.Framework;
using ${Neo.Entity.Namespace}.Controllers.Helpers;
using ${Neo.Entity.Namespace}.Controllers.Exceptions;
using ${Neo.Entity.Namespace}.Models;

namespace ${Neo.Entity.Namespace}.Controllers.Base
{
    /// <summary>Handles the basic CRUD actions for a ${Neo.Entity.ClassName}.</summary>
    /// <remarks>
    ///   <para>Database Path: WebbnessCMS.${Neo.Entity.ClassName}.</para>
    /// </remarks>
    // [Resource("${Neo.Entity.ClassName}Text", "${Neo.Entity.Namespace}.Controllers.Resources.${Neo.Entity.ClassName}Resource")]
    [DefaultAction("Error")]
    [Helper(typeof (${Neo.Entity.ClassName}Helper))]
    public abstract class ${Neo.Entity.ClassName}ControllerBase : AbstractSecureController
    {

		#region Protected Abstract Methods

        /// <summary>
        /// Prepares the new entity.
        /// </summary>
        /// <param name="surrogate">The surrogate.</param>
        protected abstract void PrepareNewEntity(${Neo.Entity.ClassName}Surrogate surrogate);

        /// <summary>
        /// Prepares to edit entity.
        /// </summary>
        /// <param name="entity">The entity.</param>
        protected abstract void PrepareToEditEntity(${Neo.Entity.ClassName} entity);
        
        #endregion
        
        #region Protected Methods
        
        /// <summary>
        /// Setup the list(s) that support this entity.
        /// </summary>
        /// <param name="entity">The entity.</param>
        protected virtual void SetSupportEntities(${Neo.Entity.ClassName} entity)
        {
#set($noDups = "")              
#foreach($column in $entity.Attributes)
#set($rel = $entity.RelationshipForAttribute($column))
#if($rel && $rel.Direction.ToString() == "Child")
#if($noDups.Contains(" $rel.ForeignEntity.ClassName.ToLower()s ") == false)
            PropertyBag["${rel.ForeignEntity.ClassName.ToLower()}s"] = GetListItems(typeof(${rel.ForeignEntity.ClassName}), ${rel.ForeignEntity.ClassName}.DefaultSortOrder, entity);
#set($noDups = "$noDups $rel.ForeignEntity.ClassName.ToLower()s ") 
#end
#end
#end
			InitRichEditFull();
        }
        
        /// <summary>
        /// Setup the list(s) that support this entity.
        /// </summary>
        protected virtual void SetSupportEntities()
        {
#set($noDups = "")              
#foreach($column in $entity.Attributes)
#set($rel = $entity.RelationshipForAttribute($column))
#if($rel && $rel.Direction.ToString() == "Child")
#if($noDups.Contains(" $rel.ForeignEntity.ClassName.ToLower()s ") == false)
            PropertyBag["${rel.ForeignEntity.ClassName.ToLower()}s"] = GetListItems(typeof(${rel.ForeignEntity.ClassName}), ${rel.ForeignEntity.ClassName}.DefaultSortOrder);
#set($noDups = "$noDups $rel.ForeignEntity.ClassName.ToLower()s ") 
#end
#end
#end
			InitRichEditFull();
        }
        
#if($entity.Constraint.Equals("unique"))
        /// <summary>
        /// Validates the constraint.
        /// </summary>
        /// <param name="surrogate">The surrogate.</param>
        /// <returns></returns>
        protected virtual bool ValidateConstraintOnCreate(${Neo.Entity.ClassName}Surrogate surrogate)
        {
            ${Neo.Entity.ClassName}Factory factory = new ${Neo.Entity.ClassName}Factory(CurrentObjectContext);
            ${Neo.Entity.ClassName}Template template = factory.GetQueryTemplate();
#foreach($column in $entity.Attributes)
#if($column.Constraint)
            template.${column.PropertyName} = surrogate.${column.PropertyName}#if($column.DotNetType != "System.String").Value #end;
#end
#end
            return factory.FindFirst(template.Qualifier) == null;          
        }
        
        /// <summary>
        /// Validates the constraint.
        /// </summary>
        /// <param name="entity">The entity.</param>
        /// <param name="surrogate">The surrogate.</param>
        /// <returns></returns>
        protected virtual bool ValidateConstraintOnUpdate(${Neo.Entity.ClassName} entity, ${Neo.Entity.ClassName}Surrogate surrogate)
        {
            return #set($gotCnt = 0)#foreach($column in $entity.Attributes)#if($column.Constraint) #if($gotCnt > 0) && #end entity.${column.PropertyName} == surrogate.${column.PropertyName}#set($gotCnt = $gotCnt + 1)#end#end ;           
        }
#end

        #endregion
        
        #region Public Methods
        
        /// <summary>Handles a request for a new ${Neo.Entity.ClassName}</summary>
        public virtual void New()
        {
        			
			if (IsAjaxRequest)
                CancelLayout();
                
			try
            {
                RunRules();
            }
            catch (RulesEvaluationException)
            {
                return;
            }
            
            if (Flash.Contains("${Neo.Entity.ClassName.ToLower()}") == false)
            {
                ReturnToPage = Params["HTTP_REFERER"];
                ${Neo.Entity.ClassName}Surrogate surrogate = new ${Neo.Entity.ClassName}Surrogate();
                PrepareNewEntity(surrogate);               
                Flash["${Neo.Entity.ClassName.ToLower()}"] = surrogate;
            }
			SetSupportEntities();
        }

        /// <summary>Handles a request to create a new ${Neo.Entity.ClassName}</summary>
        /// <param name="${Neo.Entity.ClassName.ToLower()}Surrogate">The ${Neo.Entity.ClassName.ToLower()}Surrogate.</param>
        public virtual void Create([DataBind("${Neo.Entity.ClassName}", Validate=true)] ${Neo.Entity.ClassName}Surrogate ${Neo.Entity.ClassName.ToLower()}Surrogate)
        {
            if (HasValidationError(${Neo.Entity.ClassName.ToLower()}Surrogate))
            {
                Flash["validationerrors"] = GetErrorSummary(${Neo.Entity.ClassName.ToLower()}Surrogate);
                Flash["${Neo.Entity.ClassName.ToLower()}"] = ${Neo.Entity.ClassName.ToLower()}Surrogate;
                RedirectToAction("New");
                return;
            }
            
            if (ValidateSurrogate(${Neo.Entity.ClassName.ToLower()}Surrogate) == false)
            {
                Flash["surrogatevalidationerrors"] = ${Neo.Entity.ClassName.ToLower()}Surrogate.ValidationErrors;
                Flash["${Neo.Entity.ClassName.ToLower()}"] = ${Neo.Entity.ClassName.ToLower()}Surrogate;
                RedirectToAction("New");
                return;
            }
#if($entity.Constraint.Equals("unique"))            
            if (ValidateConstraintOnCreate(${Neo.Entity.ClassName.ToLower()}Surrogate) == false)
            {
                Flash["errortext"] = "You have attempted to create a duplicate record.";
                Flash["${Neo.Entity.ClassName.ToLower()}"] = ${Neo.Entity.ClassName.ToLower()}Surrogate;
                RedirectToAction("New");
                return;
            }
#end            
            try
            {
            
#if($entity.IdMethod.ToString == "None")
#if($entity.PrimaryKeyIsForeignKey)
#foreach($combination in $entity.RelationshipSetsForColumns($entity.PkColumns))
				${Neo.Entity.ClassName} ${Neo.Entity.ClassName.ToLower()} = ($entity.ClassName) CurrentObjectContext.CreateObject(typeof($entity.ClassName), new object[]{ #foreach($column in $entity.PkColumns)#set( $pnum = $velocityCount - 1)#if( $pnum > 0),#end ${Neo.Entity.ClassName.ToLower()}Surrogate.$column.PropertyName #end } );
#end
#else
				${Neo.Entity.ClassName} ${Neo.Entity.ClassName.ToLower()} = ($entity.ClassName) CurrentObjectContext.CreateObject(typeof($entity.ClassName), new object[]{ #foreach($column in $entity.PkColumns)#set( $pnum = $velocityCount - 1)#if( $pnum > 0),#end ${Neo.Entity.ClassName.ToLower()}Surrogate.$column.PropertyName #end } );
#end
#else	 
				${Neo.Entity.ClassName} ${Neo.Entity.ClassName.ToLower()} = new ${Neo.Entity.ClassName}Factory(CurrentObjectContext).CreateObject();
#end            
                ${Neo.Entity.ClassName.ToLower()}Surrogate.BindObjectInstance(${Neo.Entity.ClassName.ToLower()});
                RunRulesAndSave(${Neo.Entity.ClassName.ToLower()});
            }
            catch (RulesEvaluationException)
            {
                return;
            }
            catch (Exception se)
            {
                ProcessErrorAndDisplay(se);
                return;
            }
            PerformRedirect("List");
        }

        /// <summary>Handles a request to edit an existing ${Neo.Entity.ClassName}</summary>
#foreach($column in $entity.PkColumns)#set( $pnum = $velocityCount - 1)
	    ///<param name="${column.PropertyName}">#if( $entity.ColumnIsForeignKey($column.ColumnName))$entity.RelationshipForAttribute($column).ForeignEntity.ClassName#else$column.Description#end.</param>
#end
        public virtual void Edit(#foreach($column in $entity.PkColumns)#set( $pnum = $velocityCount - 1)#if( $pnum > 0),#end ${column.DotNetType}#if ($column.DotNetType != "System.String")?#end $column.PropertyName #end)
        {
			if (IsAjaxRequest)
                CancelLayout();
                
            if (Flash.Contains("${Neo.Entity.ClassName.ToLower()}"))
            {
				SetSupportEntities();
            }
            else
            {
                ReturnToPage = Params["HTTP_REFERER"];
                try
                {
                    ${Neo.Entity.ClassName} ${Neo.Entity.ClassName.ToLower()} = new ${Neo.Entity.ClassName}Factory(CurrentObjectContext).FindObjectByPK(#foreach($column in $entity.PkColumns)#set( $pnum = $velocityCount - 1) ${column.PropertyName}#if ($column.DotNetType != "System.String").Value#end#if( $velocityCount < $entity.PkColumns.Count),#end#end );
                    PrepareToEditEntity(${Neo.Entity.ClassName.ToLower()});
                    RunRules(${Neo.Entity.ClassName.ToLower()});
                    PropertyBag["${Neo.Entity.ClassName.ToLower()}"] = ${Neo.Entity.ClassName.ToLower()};
                    SetSupportEntities(${Neo.Entity.ClassName.ToLower()});
                }
                catch (RulesEvaluationException)
				{
					return;
				}
                catch (Exception e)
                {
                    ProcessErrorAndDisplay(e);
                    return;
                }
            }
        }

        /// <summary>Handles a request to update an existing ${Neo.Entity.ClassName}</summary>
        public virtual void Update([DataBind("${Neo.Entity.ClassName}", Validate = true)] ${Neo.Entity.ClassName}Surrogate ${Neo.Entity.ClassName.ToLower()}Surrogate)
        {
            if (HasValidationError(${Neo.Entity.ClassName.ToLower()}Surrogate))
            {
                Flash["validationerrors"] = GetErrorSummary(${Neo.Entity.ClassName.ToLower()}Surrogate);
                Flash["${Neo.Entity.ClassName.ToLower()}"] = ${Neo.Entity.ClassName.ToLower()}Surrogate;
                RedirectToAction("Edit", #foreach($column in $entity.PkColumns)#set( $pnum = $velocityCount - 1) "${column.PropertyName}=" + ${Neo.Entity.ClassName.ToLower()}Surrogate.${column.PropertyName}#if( $velocityCount < $entity.PkColumns.Count),#end#end);
                return;
            }
            if (ValidateSurrogate(${Neo.Entity.ClassName.ToLower()}Surrogate) == false)
            {
                Flash["surrogatevalidationerrors"] = ${Neo.Entity.ClassName.ToLower()}Surrogate.ValidationErrors;
                Flash["${Neo.Entity.ClassName.ToLower()}"] = ${Neo.Entity.ClassName.ToLower()}Surrogate;
                RedirectToAction("Edit", #foreach($column in $entity.PkColumns)#set( $pnum = $velocityCount - 1) "${column.PropertyName}=" + ${Neo.Entity.ClassName.ToLower()}Surrogate.${column.PropertyName}#if( $velocityCount < $entity.PkColumns.Count),#end#end);
                return;
            } 
            try
            {
                ${Neo.Entity.ClassName} ${Neo.Entity.ClassName.ToLower()} = new ${Neo.Entity.ClassName}Factory(CurrentObjectContext).FindObjectByPK(#foreach($column in $entity.PkColumns)#set( $pnum = $velocityCount - 1) ${Neo.Entity.ClassName.ToLower()}Surrogate.${column.PropertyName}#if ($column.DotNetType != "System.String").Value#end#if( $velocityCount < $entity.PkColumns.Count),#end#end);
#if($entity.Constraint.Equals("unique")) 
                ValidateConstraintOnUpdate(${Neo.Entity.ClassName.ToLower()}, ${Neo.Entity.ClassName.ToLower()}Surrogate);
#end
                ${Neo.Entity.ClassName.ToLower()}Surrogate.BindObjectInstance(${Neo.Entity.ClassName.ToLower()});
                RunRulesAndSave(${Neo.Entity.ClassName.ToLower()});
            }
            catch (RulesEvaluationException)
			{
				return;
			}
			catch (UniqueConstraintException)
			{
				return;
			}
            catch (Exception e)
            {
                ProcessErrorAndDisplay(e);
                return;
            }
            PerformRedirect("List");
        }

        /// <summary>Handles a request to display a list of ${Neo.Entity.ClassName} items.</summary>
        public virtual void List(string sort, string dir, int page, [DataBind("${Neo.Entity.ClassName}")] ${Neo.Entity.ClassName}Surrogate ${Neo.Entity.ClassName.ToLower()}Surrogate)
        {
        			
			if (IsAjaxRequest)
                CancelLayout();
            
			ReturnToPage = Params["HTTP_REFERER"];
			
			try
            {
                RunRules();
            }
            catch (RulesEvaluationException)
            {
                return;
            }
            
            SortDirection sortDir;
            if ((page == 0))
            {
                page = 1;
            }
            if (String.IsNullOrEmpty(sort))
            {
                sortDir = SortDirection.Ascending;
                PropertyBag["dir"] = "d";
                PropertyBag["dirnow"] = "a";
#if($entity.DefaultProperty)                
                sort = "${entity.DefaultProperty}";
#else
                sort = "";
#end                
                PropertyBag["sort"] = sort;
            }
            else
            {
                if (dir.Equals("d", StringComparison.InvariantCultureIgnoreCase))
                {
                    sortDir = SortDirection.Descending;
                    PropertyBag["dir"] = "a";
                }
                else
                {
                    sortDir = SortDirection.Ascending;
                    PropertyBag["dir"] = "d";
                }
                PropertyBag["sort"] = sort;
                PropertyBag["dirnow"] = dir;
            }
            ${Neo.Entity.ClassName}Factory factory = new ${Neo.Entity.ClassName}Factory(CurrentObjectContext);
            ${Neo.Entity.ClassName}Template template = factory.GetQueryTemplate();
            ${Neo.Entity.ClassName.ToLower()}Surrogate.BindToSearchTemplate(template);
            ObjectList<${Neo.Entity.ClassName}> list = factory.Find(template);
            PropertyBag["${Neo.Entity.ClassName.ToLower()}"] = ${Neo.Entity.ClassName.ToLower()}Surrogate;
            if ((String.IsNullOrEmpty(sort) == false))
            {
                list.Sort(sort, sortDir);
            }
            
            PropertyBag["${Neo.Entity.ClassName.ToLower()}Items"] = PaginationHelper.CreatePagination(list, ITEMS_PER_PAGE, page);
			SetSupportEntities();
        }

        /// <summary>Handles a request for the details of a ${Neo.Entity.ClassName}.</summary>
#foreach($column in $entity.PkColumns)#set( $pnum = $velocityCount - 1)
	    ///<param name="${column.PropertyName}">#if( $entity.ColumnIsForeignKey($column.ColumnName))$entity.RelationshipForAttribute($column).ForeignEntity.ClassName#else$column.Description#end.</param>
#end
        public virtual void Detail(#foreach($column in $entity.PkColumns)#set( $pnum = $velocityCount - 1)#if( $pnum > 0),#end ${column.DotNetType}#if ($column.DotNetType != "System.String")?#end $column.PropertyName #end)
        {
        			
			if (IsAjaxRequest)
                CancelLayout();
                
            ReturnToPage = Params["HTTP_REFERER"];
            try
            {
                ${Neo.Entity.ClassName} ${Neo.Entity.ClassName.ToLower()} = new ${Neo.Entity.ClassName}Factory(CurrentObjectContext).FindObjectByPK(#foreach($column in $entity.PkColumns)#set( $pnum = $velocityCount - 1) ${column.PropertyName}#if ($column.DotNetType != "System.String").Value#end#if( $velocityCount < $entity.PkColumns.Count),#end#end );
                RunRules(${Neo.Entity.ClassName.ToLower()});
                PropertyBag["${Neo.Entity.ClassName.ToLower()}"] = ${Neo.Entity.ClassName.ToLower()};
                SetSupportEntities(${Neo.Entity.ClassName.ToLower()});
            }
            catch (RulesEvaluationException)
            {
                return;
            }
            catch (Exception e)
            {
                ProcessErrorAndDisplay(e);
                return;
            }
        }

        /// <summary>Handles a request to delete a ${Neo.Entity.ClassName}.</summary>
#foreach($column in $entity.PkColumns)#set( $pnum = $velocityCount - 1)
	    ///<param name="${column.PropertyName}">#if( $entity.ColumnIsForeignKey($column.ColumnName))$entity.RelationshipForAttribute($column).ForeignEntity.ClassName#else$column.Description#end.</param>
#end
        public virtual void Delete(#foreach($column in $entity.PkColumns)#set( $pnum = $velocityCount - 1)#if( $pnum > 0),#end ${column.DotNetType}#if ($column.DotNetType != "System.String")?#end $column.PropertyName #end)
        {
            try
            {
                ${Neo.Entity.ClassName} ${Neo.Entity.ClassName.ToLower()} = new ${Neo.Entity.ClassName}Factory(CurrentObjectContext).FindObjectByPK(#foreach($column in $entity.PkColumns)#set( $pnum = $velocityCount - 1) ${column.PropertyName}#if ($column.DotNetType != "System.String").Value#end#if( $velocityCount < $entity.PkColumns.Count),#end#end );
                RunRulesAndDelete(${Neo.Entity.ClassName.ToLower()}); 
            }
            catch (RulesEvaluationException)
            {
                return;
            }
            catch (Exception e)
            {
                ProcessErrorAndDisplay(e);
                return;
            }
            PerformRedirect("List");
        }

        /// <summary>Handles a request to display a ${Neo.Entity.ClassName}.</summary>
#foreach($column in $entity.PkColumns)#set( $pnum = $velocityCount - 1)
	    ///<param name="${column.PropertyName}">#if( $entity.ColumnIsForeignKey($column.ColumnName))$entity.RelationshipForAttribute($column).ForeignEntity.ClassName#else$column.Description#end.</param>
#end
        public virtual void Index(#foreach($column in $entity.PkColumns)#set( $pnum = $velocityCount - 1)#if( $pnum > 0),#end ${column.DotNetType}#if ($column.DotNetType != "System.String")?#end $column.PropertyName #end)
        {
        			
			if (IsAjaxRequest)
                CancelLayout();
            
            ReturnToPage = Params["HTTP_REFERER"];
            try
            {
                ${Neo.Entity.ClassName} ${Neo.Entity.ClassName.ToLower()} = new ${Neo.Entity.ClassName}Factory(CurrentObjectContext).FindObjectByPK(#foreach($column in $entity.PkColumns)#set( $pnum = $velocityCount - 1) ${column.PropertyName}#if ($column.DotNetType != "System.String").Value#end#if( $velocityCount < $entity.PkColumns.Count),#end#end );
                RunRules(${Neo.Entity.ClassName.ToLower()});
                PropertyBag["${Neo.Entity.ClassName.ToLower()}"] = ${Neo.Entity.ClassName.ToLower()};
            }
            catch (RulesEvaluationException)
            {
                return;
            }
            catch (Exception e)
            {
                ProcessErrorAndDisplay(e);
                return;
            }
        }
        
        #endregion
    }
}